package com.lbj.yuanxi.yx001

import android.annotation.SuppressLint
import android.content.Context
import android.graphics.*
import android.util.AttributeSet
import android.view.GestureDetector
import android.view.MotionEvent
import android.view.View
import android.widget.Toast
import com.lbj.yuanxi.tool.dp2pxF
import com.lbj.yuanxi.tool.sp2pxF

@SuppressLint("ClickableViewAccessibility")
class FloatingProgressView @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {

    // 定义背景圆画笔
    private val circlePaint = Paint()

    // 定义进度画笔
    private val progressPaint = Paint()

    // 定义文字画笔
    private val textPaint = Paint()

    // 定义路径
    private val path = Path()

    // 双击时消息通信时间
    private val doubleAnimTime = 50L
    private val singleAnimTime = 100L

    // 单击动画执行次数
    private var singleAnimCount = 30
    private var singleAnimCurrentCount = 30

    private var isSingleTap = false

    // 定义画布
    private val bitmapCanvas: Canvas

    // 定义画布上面的bitmap
    private val bitmap: Bitmap

    // 定义图片的宽度
    private val mWidth = 200.dp2pxF()

    // 定义图片的高度
    private val mHeight = 200.dp2pxF()

    // 定义当前进度
    private var current = 0

    // 定义能到达的最大进度
    private val progress = 50

    // 定义最大进度
    private val max = 100

    // 事件监听
    private val gestureDetector: GestureDetector

    init {
        circlePaint.isAntiAlias = true
        circlePaint.color = Color.argb(0xff, 0x3a, 0x8c, 0x6c)

        progressPaint.isAntiAlias = true
        progressPaint.color = Color.argb(0xff, 0x4e, 0xc9, 0x63)
        // 设置混合模式，只保留重叠部分
        progressPaint.xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC_IN)

        textPaint.isAntiAlias = true
        textPaint.color = Color.WHITE
        textPaint.textSize = 20.sp2pxF()

        // 为什么要创建一个Bitmap?
        // 因为 progressPaint.xfermode 设置了混合模型，如果直接在Canvas中绘制则不会出现混合模式
        bitmap = Bitmap.createBitmap(mWidth.toInt(), mHeight.toInt(), Bitmap.Config.ARGB_8888)
        bitmapCanvas = Canvas(bitmap)

        // 创建手势监听类
        gestureDetector =
            GestureDetector(context, object : GestureDetector.SimpleOnGestureListener() {

                override fun onSingleTapConfirmed(e: MotionEvent?): Boolean {
                    Toast.makeText(context, "单击了", Toast.LENGTH_SHORT).show()
                    startSingleAnimator()
                    return super.onSingleTapConfirmed(e)
                }

                override fun onDoubleTap(e: MotionEvent?): Boolean {
                    Toast.makeText(context, "双击了", Toast.LENGTH_SHORT).show()
                    startDoubleAnimator()
                    return super.onDoubleTap(e)
                }
            })

        // 将触摸事件交给手势识别
        setOnTouchListener { _, event ->
            return@setOnTouchListener gestureDetector.onTouchEvent(event)
        }

        // 让控件可以被点击，否则将不能被触摸
        isClickable = true
    }

    /**
     * 开启双击时动画
     */
    private fun startDoubleAnimator() {
        isSingleTap = false
        current = 0
        handler.postDelayed(doubleRunnable, doubleAnimTime)
    }

    // 定义双击时子线程事件
    private val doubleRunnable = DoubleRunnable()

    inner class DoubleRunnable : Runnable {
        override fun run() {
            current++
            if (current <= progress) {
                invalidate()
                handler.postDelayed(doubleRunnable, doubleAnimTime)
            } else {
                handler.removeCallbacks(doubleRunnable)
            }
        }
    }

    /**
     * 开启单击时动画
     */
    private fun startSingleAnimator() {
        isSingleTap = true
        handler.postDelayed(singleRunnable, singleAnimTime)
    }

    private val singleRunnable = SingleRunnable()

    inner class SingleRunnable : Runnable {
        override fun run() {
            if (singleAnimCurrentCount >= 0) {
                invalidate()
                handler.postDelayed(singleRunnable, singleAnimTime)
                singleAnimCurrentCount--
            } else {
                singleAnimCurrentCount = singleAnimCount
            }
        }
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        setMeasuredDimension(mWidth.toInt(), mHeight.toInt())
    }

    override fun onDraw(canvas: Canvas) {
        // 绘制背景圆
        bitmapCanvas.drawCircle(mWidth / 2, mHeight / 2, mWidth / 2, circlePaint)

        // 重置路径
        path.reset()
        // 获取到进度的高
        val y = (1 - current / max.toFloat()) * mHeight
        // 按照顺时针连接路径
        path.moveTo(mWidth, y)
        path.lineTo(mWidth, mHeight)
        path.lineTo(0f, mHeight)
        path.lineTo(0f, y)

        // 进度上层的左右2个点进行连接

        if (isSingleTap) {
            val d = (singleAnimCurrentCount / singleAnimCount) * 20
            if (singleAnimCurrentCount % 2 == 0) {
                for (i in 0 until 5) {

                    path.rQuadTo(10.dp2pxF(), (-d).dp2pxF(), 20.dp2pxF(), 0.dp2pxF())
                    path.rQuadTo(10.dp2pxF(), d.dp2pxF(), 20.dp2pxF(), 0.dp2pxF())
                }
            } else {
                for (i in 0 until 5) {
                    path.rQuadTo(20.dp2pxF(), d.dp2pxF(), 40.dp2pxF(), 0.dp2pxF())
                    path.rQuadTo(20.dp2pxF(), (-d).dp2pxF(), 40.dp2pxF(), 0.dp2pxF())
                }
            }

        } else {
            val d = (1 - current.toFloat() / progress) * 10

            for (i in 0 until 5) {
                path.rQuadTo(10.dp2pxF(), (-d).dp2pxF(), 20.dp2pxF(), 0.dp2pxF())
                path.rQuadTo(10.dp2pxF(), d.dp2pxF(), 20.dp2pxF(), 0.dp2pxF())
            }
        }

        path.close()

        bitmapCanvas.drawPath(path, progressPaint)

        // 注意这里执行部分，设置文字的步骤必须在设置进度后面
        // 因为设置进度使用了混合模式，重叠部分才会展示，如果提前设置文字，则不会展示文字，除非文字在进度之中

        val text = "${((current / max.toFloat()) * 100).toInt()}%"
        val textWidth = textPaint.measureText(text)

        val baseLine = textPaint.fontMetrics.ascent + textPaint.fontMetrics.descent

        bitmapCanvas.drawText(
            text,
            mWidth / 2 - textWidth / 2,
            mHeight / 2 - baseLine / 2,
            textPaint
        )

        // 将最终的bitmap绘制到canvas上
        canvas.drawBitmap(bitmap, 0f, 0f, null)
    }
}